﻿Public Class BanneredGrid : Inherits Grid



    Public Grip As GripLabel
    Public Banner As New KBanner
    Public ContentGrid As New Grid
    Private _title As String



    Public Property Title() As String
        Get
            Return _title
        End Get
        Set(ByVal value As String)
            _title = value
            Grip.Content = _title
        End Set
    End Property

    Public Sub New()


        HorizontalAlignment = Windows.HorizontalAlignment.Stretch
        VerticalAlignment = Windows.VerticalAlignment.Stretch

        Dim rd As New RowDefinition With {.Height = GridLength.Auto}
        RowDefinitions.Add(rd)  '|->    prima riga per GRIP

        rd = New RowDefinition With {.Height = New GridLength(1, GridUnitType.Star)}
        RowDefinitions.Add(rd)  '|->    seconda riga per COINTENTGRID




        'CONTENTGRID
        ContentGrid.HorizontalAlignment = Windows.HorizontalAlignment.Stretch
        ContentGrid.VerticalAlignment = Windows.VerticalAlignment.Stretch
        ContentGrid.Background = Brushes.Snow
        Grid.SetRow(ContentGrid, 1)
        Grid.SetRowSpan(ContentGrid, 1)
        Grid.SetColumnSpan(ContentGrid, 1)

        'BANNER
        Banner.HorizontalAlignment = Windows.HorizontalAlignment.Stretch
        Banner.VerticalAlignment = Windows.VerticalAlignment.Top
        ' Banner.Background = Brushes.Teal
        Banner.PART_Body.Content = "K-Dock"
        Grid.SetRow(Banner, 0)
        Grid.SetRowSpan(Banner, 1)
        'Grid.SetColumnSpan(Banner, 1)
        Banner.Height = 20



        Children.Add(Banner)
        Children.Add(ContentGrid)

        'plugs the reference.
        Grip = Banner.PART_Body
    End Sub

    Public Sub New(ByVal ttl As String)
        MyClass.New()
        Title = ttl
    End Sub

    Public Overridable Sub Dispose()
        Grip.PuppetWindow = Nothing
        Children.Remove(Grip)

        Banner.PART_Icon.Source = Nothing
        Children.Remove(Banner)
        Banner = Nothing

        Children.Remove(ContentGrid)
        ContentGrid = Nothing

        _title = Nothing



        GC.SuppressFinalize(Me)
    End Sub

End Class

Public NotInheritable Class KContextMenu : Inherits ContextMenu
    Public AttachedKGrid As KGrid

    Public _MI_Float As MenuItem
    Public _MI_Dock As MenuItem
    Public _MI_Unpin As MenuItem
    Public _MI_Close As MenuItem

    Public Sub New()
        _MI_Float = New MenuItem With {.Header = "Float"}
        _MI_Dock = New MenuItem With {.Header = "Dock"}
        _MI_Unpin = New MenuItem With {.Header = "Unpin"}
        _MI_Close = New MenuItem With {.Header = "Close"}


        Items.Add(_MI_Float)
        Items.Add(_MI_Dock)
        Items.Add(_MI_Unpin)
        Items.Add(_MI_Close)
    End Sub

    Public Sub Reset()
        _MI_Float.IsEnabled = True
        _MI_Dock.IsEnabled = True
        _MI_Unpin.IsEnabled = True
        _MI_Close.IsEnabled = True
    End Sub

End Class

Public Class KGrid : Inherits BanneredGrid

    Protected Shared _CtxtMenu As KContextMenu
    Protected Shared _CtxtMenuAlreadyBuilt As Boolean = False

    <Flags()>
    Public Enum KGridState
        Docked = 1
        Float = 2
        Pinned = 4

        L = 8
        T = 16
        R = 32
        B = 64
        C = 128

        Soft = 256
        Hard = 512

        Unpinned = 1024

    End Enum

#Region "PROPs"
    Private _state As KGrid.KGridState
    Protected _mdg As MainDockGrid
    Public _AttachedHandleButton As KButton

    Public Property State() As KGridState
        Get
            Return _state
        End Get
        Set(ByVal value As KGridState)
            _state = value
            Banner.PART_MiddleButton.Visibility = Windows.Visibility.Visible
            If _state.HasFlag(KGridState.Unpinned) And _state.HasFlag(KGridState.Hard) Then
                ' Banner.Background = Brushes.SlateBlue

                ActivateBanner()
                'ElseIf MDG.GetVeryBaseGrid Is Me Then
                '    Banner.PART_MiddleButton.Visibility = Windows.Visibility.Collapsed
            Else

                '  Banner.Background = Brushes.Teal
                DeactivateBanner()
            End If

           
        End Set
    End Property

    Public Property MDG() As MainDockGrid
        Get
            Return _mdg
        End Get
        Set(ByVal value As MainDockGrid)
            If value IsNot Nothing And _mdg IsNot value Then
                _mdg = value
                AddHandler Banner.PART_LeftButton.Click, AddressOf onLeftButtonClick
                AddHandler Banner.PART_MiddleButton.Click, AddressOf onMiddleButtonClick
                AddHandler Banner.PART_RightButton.Click, AddressOf onRightButtonClick
                '  AddHandler Banner.PART_Body.MouseDown, AddressOf onBannerMouseDown
                BuildContextMenu()
            End If
        End Set
    End Property

#End Region

#Region "c.tor"
    Public Sub New()
        MyBase.New()

        'Sistema i pulsanti del banner
        PrepareLayout()

    End Sub



    Public Sub New(ByRef m As MainDockGrid, ByVal ttl As String)
        MyBase.New(ttl)

        MDG = m

        If MDG.MDGBannersStyle IsNot Nothing Then
            '   Banner.Background = DependencyProperty.UnsetValue
            Banner.Style = MDG.MDGBannersStyle
            Banner.PART_LeftButton.Style = MDG.MDGBannersButtonsStyle
            Banner.PART_MiddleButton.Style = MDG.MDGBannersButtonsStyle
            Banner.PART_RightButton.Style = MDG.MDGBannersButtonsStyle

        End If

        PrepareLayout()

    End Sub

    Public Sub New(ByRef m As MainDockGrid)
        MyClass.New(m, "")
    End Sub

#End Region

#Region "METHODS - shared"
    Protected Shared Function CalculateDockingSide(ByVal s As KGridState) As MainDockGrid.DockPosition
        If s.HasFlag(KGridState.L) Then
            Return MainDockGrid.DockPosition.Left
        End If
        If s.HasFlag(KGridState.T) Then
            Return MainDockGrid.DockPosition.Top
        End If
        If s.HasFlag(KGridState.R) Then
            Return MainDockGrid.DockPosition.Right
        End If
        If s.HasFlag(KGridState.B) Then
            Return MainDockGrid.DockPosition.Bottom
        End If

        Return Nothing
    End Function

    Public Shared Function GetLTRB(ByRef Kg As KGrid) As KGridState
        If Kg.State.HasFlag(KGridState.L) Then Return KGridState.L
        If Kg.State.HasFlag(KGridState.R) Then Return KGridState.R
        If Kg.State.HasFlag(KGridState.T) Then Return KGridState.T
        If Kg.State.HasFlag(KGridState.B) Then Return KGridState.B
        Return Nothing
    End Function

    Public Shared Function GetGenState(ByRef Kg As KGrid) As KGridState
        If Kg.State.HasFlag(KGridState.Docked) Then Return KGridState.Docked
        If Kg.State.HasFlag(KGridState.Float) Then Return KGridState.Float
        If Kg.State.HasFlag(KGridState.Pinned) Then Return KGridState.Pinned
        If Kg.State.HasFlag(KGridState.Unpinned) Then Return KGridState.Unpinned
        Return Nothing
    End Function

    Public Shared Function GetSoftHard(ByRef Kg As KGrid) As KGridState
        If Kg.State.HasFlag(KGridState.Soft) Then Return KGridState.Soft
        If Kg.State.HasFlag(KGridState.Hard) Then Return KGridState.Hard
        Return Nothing
    End Function
#End Region

#Region "METHODS - instance"
    Private Sub BuildContextMenu()
        If _CtxtMenuAlreadyBuilt Then Return
        _CtxtMenu = New KContextMenu
        _CtxtMenu.HasDropShadow = True

        AddHandler _CtxtMenu._MI_Float.Click, AddressOf _Clk_01
        AddHandler _CtxtMenu._MI_Dock.Click, AddressOf _Clk_02
        AddHandler _CtxtMenu._MI_Unpin.Click, AddressOf _Clk_03
        AddHandler _CtxtMenu._MI_Close.Click, AddressOf _Clk_04


        _CtxtMenuAlreadyBuilt = True
    End Sub

    Public Overridable Sub ShowCtxtMenu(ByRef caller As KGrid)
        _CtxtMenu.Reset()
        _CtxtMenu.AttachedKGrid = caller
        _CtxtMenu.PlacementTarget = caller.Banner.PART_LeftButton

        'adoro la possibilità di modifica lo stato dei pulsanti in base allo stato dei grids.
        If _CtxtMenu.AttachedKGrid.State.HasFlag(KGrid.KGridState.Docked) Then
            _CtxtMenu._MI_Dock.IsEnabled = False
        End If

        If _CtxtMenu.AttachedKGrid.State.HasFlag(KGrid.KGridState.Unpinned) Then
            _CtxtMenu._MI_Unpin.IsEnabled = False
        End If

        If _CtxtMenu.AttachedKGrid.State.HasFlag(KGrid.KGridState.Float) Then
            _CtxtMenu._MI_Float.IsEnabled = False
            _CtxtMenu._MI_Unpin.IsEnabled = False
        End If

        If _mdg IsNot Nothing And _CtxtMenu.AttachedKGrid Is MDG.GetVeryBaseGrid Then
            _CtxtMenu._MI_Unpin.IsEnabled = False
        End If

        _CtxtMenu.IsOpen = True
    End Sub

    Public Sub ActivateBanner()
        Banner.IsActivated = True
    End Sub

    Public Sub DeactivateBanner()
        Banner.IsActivated = False
    End Sub

    Private Sub PrepareLayout()
        Banner.PART_LeftButton.Content = "6"  'v
        Banner.PART_LeftButton.FontFamily = New FontFamily("Webdings")

        Banner.PART_MiddleButton.Content = "ë"    'pin symbol
        Banner.PART_MiddleButton.FontFamily = New FontFamily("Webdings")

        Banner.PART_RightButton.Content = "r" 'chiusura X
        Banner.PART_RightButton.FontFamily = New FontFamily("Webdings")

    End Sub

#End Region

#Region "EVENTS"

    Public Sub onLeftButtonClick(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
        ShowCtxtMenu(Me)
    End Sub
    Public Sub onMiddleButtonClick(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)


        If State.HasFlag(KGridState.Float) Then
            If Grip.PuppetWindow.WindowState = WindowState.Maximized Then
                Grip.PuppetWindow.WindowState = WindowState.Normal
                Banner.PART_MiddleButton.Content = "1"  ' maximize []]
            Else
                Grip.PuppetWindow.WindowState = WindowState.Maximized
                Banner.PART_MiddleButton.Content = "2"  ' restore []]
            End If

            Return
        End If

        If State.HasFlag(KGridState.Unpinned) Then
            _Dock()
        Else
            _Unpin()
        End If

    End Sub
    Public Sub onRightButtonClick(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)

        _Close()
    End Sub


    Public Sub _Clk_01(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
        ' _CtxtMenu.AttachedKGrid.MDG.FloatGrid_Ex(_CtxtMenu.AttachedKGrid)
        _CtxtMenu.AttachedKGrid._Float()
    End Sub
    Public Sub _Clk_02(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
        '  _CtxtMenu.AttachedKGrid.MDG.DetachUnpinnedGrid(_CtxtMenu.AttachedKGrid)
        ' _CtxtMenu.AttachedKGrid.MDG.DockCard(_CtxtMenu.AttachedKGrid, MDG.GetVeryBaseGrid(), DKFromState(_CtxtMenu.AttachedKGrid.State))
        _CtxtMenu.AttachedKGrid._Dock()
    End Sub
    Public Sub _Clk_03(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
        ' _CtxtMenu.AttachedKGrid.MDG.Unpin(_CtxtMenu.AttachedKGrid, MDG.CalculateUnpinningSide(_CtxtMenu.AttachedKGrid))
        _CtxtMenu.AttachedKGrid._Unpin()
    End Sub
    Public Sub _Clk_04(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)

        ' _CtxtMenu.AttachedKGrid.MDG.DetachKGrid(_CtxtMenu.AttachedKGrid)

        ' _CtxtMenu.AttachedKGrid.Dispose()
        _CtxtMenu.AttachedKGrid._Close()
        'Me = l'istanza di Kgrid in cui sono state aggiunti questi handler.
    End Sub



    Protected Overridable Sub _Float()
        MDG.FloatGrid_Ex(Me)
        Banner.PART_MiddleButton.Content = "1"  ' maximize []
    End Sub

    Protected Overridable Sub _Dock()


        MDG.DetachUnpinnedGrid(Me)

        If State.HasFlag(KGridState.Float) Then
            MDG.DockCard(Me, MDG.GetVeryBaseGrid(), CalculateDockingSide(State), Grip.PuppetWindow)

        Else
            MDG.DockCard(Me, MDG.GetVeryBaseGrid(), CalculateDockingSide(State))
        End If

        Banner.PART_MiddleButton.Content = "ë"  ' pin simbol []]
    End Sub

    Protected Overridable Sub _Unpin()
        If Me Is MDG.GetVeryBaseGrid Then Return
        MDG.Unpin(Me, MDG.CalculateUnpinningSide(Me))
    End Sub

    Protected Overridable Sub _Close()
        MDG.DetachKGrid(Me)
        If Me.Grip.PuppetWindow IsNot Nothing Then  'Mi aspetto che PuppetWindow riferisca alla Window a cui questo Kgrid appartiene.
            Me.Grip.PuppetWindow.Close()
        End If
        Dispose()
    End Sub


#End Region

#Region "disposition"

    Public Overrides Sub Dispose()
        MyBase.Dispose()

        ' Grip.PuppetWindow = Nothing
        If _AttachedHandleButton IsNot Nothing Then
            _AttachedHandleButton.AttachedKGrid = Nothing
            _AttachedHandleButton = Nothing
        End If
        _mdg = Nothing
        ' GC.SuppressFinalize(Me)
    End Sub
#End Region

End Class

Public Class CentrKGrid : Inherits KGrid


    Public TabsGrid As Grid
    Public KGrids As New List(Of KGrid)
    Public CurrentlyVisibleKG As KGrid

    Private bannerheight As Double = 20

    ' Private _mdg As MainDockGrid
    Public Shadows Property MDG() As MainDockGrid
        Get
            Return _mdg
        End Get
        Set(ByVal value As MainDockGrid)
            If value IsNot Nothing And _mdg IsNot value Then
                _mdg = value
                AddHandler Banner.PART_LeftButton.Click, AddressOf onLeftButtonClick
                AddHandler Banner.PART_MiddleButton.Click, AddressOf onMiddleButtonClick
                AddHandler Banner.PART_RightButton.Click, AddressOf onRightButtonClick
                ' AddHandler Banner.PART_Body.MouseDown, AddressOf onBannerMouseDown
            End If
        End Set
    End Property

    Private Sub PrepareLayout()

        Dim RtabsGridIndex = Math.Max(RowDefinitions.Count, 0)
        Dim CtabsGridIndex = Math.Max(ColumnDefinitions.Count, 0)

        RowDefinitions.Insert(RtabsGridIndex, New RowDefinition With {.Height = New GridLength(bannerheight)})

        TabsGrid = New Grid

        Grid.SetRow(TabsGrid, RtabsGridIndex)
        Grid.SetColumn(TabsGrid, CtabsGridIndex)
        Grid.SetRowSpan(TabsGrid, 1)
        Grid.SetColumnSpan(TabsGrid, 1)

        Dim stackbuttons As New StackPanel
        'stackbuttons.Width = Double.NaN
        'stackbuttons.Height = Double.NaN
        'stackbuttons.VerticalAlignment = Windows.VerticalAlignment.Stretch
        'stackbuttons.HorizontalAlignment = Windows.HorizontalAlignment.Stretch
        stackbuttons.Orientation = Orientation.Horizontal
        ' stackbuttons.Background = Nothing
        TabsGrid.Children.Add(stackbuttons)

        Children.Add(TabsGrid)



       

      


    End Sub



    Public Sub New()
        MyBase.New()

        PrepareLayout()
    End Sub


    Public Sub New(ByRef m As MainDockGrid, ByVal ttl As String)
        MyBase.New(m, ttl)

        ' MDG = m
        ' Title = ttl

        PrepareLayout()
    End Sub

    Public Sub New(ByRef m As MainDockGrid)
        MyClass.New(m, "")
    End Sub



    Public Sub AddTab(ByRef g As KGrid)
        ContentGrid.Children.Add(g)
        g.Banner.Visibility = Windows.Visibility.Collapsed

        KGrids.Add(g)

        Dim btn As New KButton
        btn.Content = g.Title
        btn.AttachedKGrid = g
        'inietta lo stile dei pulsanti.
        btn.Style = MDG.MDGTabsStyle


        AddHandler btn.Click, AddressOf onTabButtonClick
        DirectCast(TabsGrid.Children(0), StackPanel).Children.Add(btn)

        CurrentlyVisibleKG = g

        Title = CurrentlyVisibleKG.Title

    End Sub
    Public Sub onTabButtonClick(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
        CurrentlyVisibleKG.Visibility = Windows.Visibility.Collapsed

        Dim kbut As KButton = sender
        Panel.SetZIndex(kbut.AttachedKGrid, 1)
        kbut.AttachedKGrid.Visibility = Windows.Visibility.Visible
        Title = kbut.AttachedKGrid.Title

        CurrentlyVisibleKG = kbut.AttachedKGrid
    End Sub



    Public Shadows Sub onLeftButtonClick(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
        ShowCtxtMenu(Me)
    End Sub
    Public Shadows Sub onRightButtonClick(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
        '  MDG.FloatGrid_Ex(Me, True)

        ' DirectCast(Grip.PuppetWindow, Window).Close()
        ' GC.SuppressFinalize(Me)



        ' Dispose()

        '  _Float()

        ' Dispose()

        _Close()
    End Sub
    Public Shadows Sub onMiddleButtonClick(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)

        If State.HasFlag(KGridState.Float) Then
            If Grip.PuppetWindow.WindowState = WindowState.Maximized Then
                Grip.PuppetWindow.WindowState = WindowState.Maximized
                Banner.PART_MiddleButton.Content = "2"  ' restore []]
            Else
                Grip.PuppetWindow.WindowState = WindowState.Normal
                Banner.PART_MiddleButton.Content = "1"  ' maximize []]
            End If

            Return
        End If


        For x = 0 To KGrids.Count - 1
            Dim kgr As KGrid = KGrids(0)
            KGrids.RemoveAt(0)
            ContentGrid.Children.Remove(kgr)
            kgr.Banner.Visibility = Windows.Visibility.Visible
            MDG.Unpin(kgr, MDG.CalculateUnpinningSide(Me))
        Next


        MDG.DetachDockedGrid(Me)            'Se si vuole implementare il pinnin di finestre unpinnate che prima appartenevano ad un centrKgrid, è necessario impedire la distruzione di questo. Per impedirlo, commenta questa istruzione.
        Dispose()
    End Sub


    Public Overrides Sub ShowCtxtMenu(ByRef caller As KGrid)

        _CtxtMenu.Reset()
        _CtxtMenu.AttachedKGrid = caller
        _CtxtMenu.PlacementTarget = caller.Banner.PART_LeftButton

        'adoro la possibilità di modifica lo stato dei pulsanti in base allo stato dei grids.
        '  If _CtxtMenu.AttachedKGrid.State.HasFlag(KGrid.KGridState.Docked) Then
        ' _CtxtMenu._MI_Dock.IsEnabled = False
        ' End If

        If _CtxtMenu.AttachedKGrid.State.HasFlag(KGrid.KGridState.Unpinned) Then
            _CtxtMenu._MI_Unpin.IsEnabled = False
        End If

        If _CtxtMenu.AttachedKGrid.State.HasFlag(KGrid.KGridState.Float) Then
            _CtxtMenu._MI_Float.IsEnabled = False
            _CtxtMenu._MI_Unpin.IsEnabled = False
        End If

        If _CtxtMenu.AttachedKGrid.State.HasFlag(KGrid.KGridState.Docked) Then
            _CtxtMenu._MI_Dock.IsEnabled = False
        End If

        If _mdg IsNot Nothing And _CtxtMenu.AttachedKGrid Is MDG.GetVeryBaseGrid Then
            _CtxtMenu._MI_Unpin.IsEnabled = False
        End If

        _CtxtMenu.IsOpen = True
    End Sub




    Protected Overrides Sub _Float()
        MDG.FloatGrid_Ex(Me)
        Banner.PART_MiddleButton.Content = "1"  ' maximize []
    End Sub

    Protected Overrides Sub _Dock()

        '   k.MDG.DetachUnpinnedGrid(k)
        ' k.MDG.DockCard(k, k.MDG.GetVeryBaseGrid(), KGrid.DKFromState(State))
        MDG.DetachUnpinnedGrid(Me)

        If State.HasFlag(KGridState.Float) Then
            MDG.DockCard(Me, MDG.GetVeryBaseGrid(), CalculateDockingSide(State), Grip.PuppetWindow)
        Else
            MDG.DockCard(Me, MDG.GetVeryBaseGrid(), CalculateDockingSide(State))
        End If

        Banner.PART_MiddleButton.Content = "ë"  ' pin simbol []]
    End Sub

    Protected Overrides Sub _Unpin()
        If Me Is MDG.GetVeryBaseGrid Then Return
        '  Dim ck As CentrKGrid = k
        For x = 0 To KGrids.Count - 1
            Dim kgr As KGrid = KGrids(0)
            KGrids.RemoveAt(0)
            ContentGrid.Children.Remove(kgr)
            kgr.Banner.Visibility = Windows.Visibility.Visible
            MDG.Unpin(kgr, MDG.CalculateUnpinningSide(Me))
        Next

        'MDG.DetachDockedGrid(Me)            'Se si vuole implementare il pinnin di finestre unpinnate che prima appartenevano ad un centrKgrid, è necessario impedire la distruzione di questo. Per impedirlo, commenta questa istruzione.
        _Close()
    End Sub

    Protected Overrides Sub _Close()
        MDG.DetachKGrid(Me)
        If Me.Grip.PuppetWindow IsNot Nothing Then  'Mi aspetto che PuppetWindow riferisca alla Window a cui questo Kgrid appartiene.
            Me.Grip.PuppetWindow.Close()
        End If
        Dispose()
    End Sub



    Public Overrides Sub Dispose()
        MyBase.Dispose()


        TabsGrid.Children.Clear()
        TabsGrid = Nothing
        CurrentlyVisibleKG = Nothing
        KGrids.Clear()
        KGrids = Nothing
        _mdg = Nothing
        'GC.SuppressFinalize(Me)
    End Sub

    Public Overrides Function ToString() As String
        Return String.Format("K-Dock: KGrid : {0}", Title)
    End Function

End Class


